package com.jinhongone.pattern.creater.singleton.demo8;

import java.io.Serializable;

/*
* 懒汉模式-静态内部类方式（线程安全）[推荐]
* jvm在初始化类时不会同步初始其内部类，所以只有在调用getInstance()时才会初始静态内部类，由于是静态内部类的静态成员变量不存在线程安全问题。
* 类似如一个可控制触发时间的饿汉式单例模式
* java中内部类是视为外部类的一部分，所以在外部类可以直接访问内部类的private变量。
* */
public class Singleton implements Serializable {

    private static boolean flag = false;
    private Singleton(){
/*       解决反射破解单例模式方案
       方案详解：1.由于INSTANCE在内部类,外部类没有Singleton类型变量，不能像pdf中一样直接判断是否为null，所以在外部类添加flag
               2.flag可能存在线程安全问题，添加synchronized方法块
               3.第一次通过反射获取实例，可以new对象，但new完后需要将flag改为true,后续直接包异常，通过抛异常阻止new多次对象
*/
        synchronized (Singleton.class){
            if(flag){
                throw new RuntimeException("Serializable 不能创建多个");
            }
            flag = true;
//            直接在外部类调用内部类，会让内部类直接初始化，SingleTonHander.INSTANCE就会赋值，不会为null,且无法返回SingleTonHander.INSTANCE
//            if(SingleTonHander.INSTANCE != null){
//                return SingleTonHander.INSTANCE;  //无法返回对象
//                throw new RuntimeException("通过正确渠道，获取实例");
//            }

        }

    };

    private static class SingleTonHander{
        private static  final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return SingleTonHander.INSTANCE;
    }
}
